package com.menghao.rpc.provider.regisiter;

import com.menghao.rpc.RpcConstants;
import com.menghao.rpc.exception.InitializationException;
import com.menghao.rpc.provider.model.ProviderKey;
import com.menghao.rpc.spring.ProviderPostProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.MessageFormat;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * <p>本地服务仓库.</br>
 * <p>存放了契约与服务bean的映射关系</p>
 *
 * @author MarvelCode
 * @see ProviderRegister
 */
public class ProviderRepository {

    private static final Logger LOGGER = LoggerFactory.getLogger(ProviderPostProcessor.class);

    private ConcurrentMap<ProviderKey, Object> providerMapping = new ConcurrentHashMap<>();

    private Set<ProviderKey> providers = Collections.unmodifiableSet(providerMapping.keySet());

    /**
     * 注册服务，维护契约与单例的映射关系
     *
     * @param sourceInterface @Provider标识的接口
     * @param implCode        服务实现的beanName
     * @param bean            服务单例
     */
    public void register(Class sourceInterface, String implCode, Object bean) {
        ProviderKey providerKey = new ProviderKey(sourceInterface.getName(), implCode);
        LOGGER.info(RpcConstants.LOG_RPC_PREFIX + "register provider-" + providerKey);
        if (providerMapping.containsKey(providerKey)) {
            throw new InitializationException(MessageFormat.format("contract: {0} ,implCode: {1} conflict",
                    sourceInterface.getName(), implCode));
        }
        providerMapping.putIfAbsent(providerKey, bean);
    }

    /**
     * 发现服务单例，根据契约与单例的映射关系查到单例，以便反射调用
     *
     * @param providerKey 服务单例的键（契约）
     * @return 服务单例
     */
    public Object getProvider(ProviderKey providerKey) {
        return providerMapping.get(providerKey);
    }

    /**
     * 获取所有满足条件的（@Provider）的契约
     *
     * @return 服务键集合
     */
    Set<ProviderKey> getProviders() {
        return providers;
    }
}
